package org.new9uy.tetris.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.new9uy.tetris.Settings;
import org.new9uy.tetris.controller.GUIController;
import org.new9uy.tetris.game.player.ai.Bot;
import org.new9uy.tetris.game.type.Game;
import org.new9uy.tetris.game.player.Human;
import org.new9uy.tetris.game.player.Player;

//@SuppressWarnings("serial")
public class LobbyPanel
//	extends JPanel
//	implements ActionListener
{
    /*
    private JButton start;
    private JComboBox startlvl;
    private JComboBox botlvl;
    private JComboBox opt1;
    private JComboBox opt2;
    private JLabel opt1label;
    private JLabel opt2label;
    //PLAYER SETTING VARS:
    private JComboBox playerhumanity;
    private JTextField playername;
    
    private static final Dimension PLAYER_COLUMN_DIM = new Dimension(30, 30);
    private static final Dimension COMBOBOX_DIM = new Dimension(70, 30);
    private static final Dimension READY_COLUMN_DIM = new Dimension(30, 30);
	
	public LobbyPanel()
    {
	super();

	setLayout(new BorderLayout(30, 20));

	add(createPlayerSettingsPanel(), "Center");
	add(createGameSettingsPanel(mod), "East");
	add(createChatPanel(), "South");
	
	start.setEnabled(false);
	
	playerhumanity.setEnabled(false);
    }

    private JPanel createPlayerSettingsPanel()
    {
	JPanel p = new JPanel(new BorderLayout());

	p.add(createSlotColumn(), "West");
	p.add(createPlayerColumn(), "Center");
	p.add(createReadyColumn(), "East");
	addBorder(p, "Player");

	return p;
    }

    private JPanel createSlotColumn()
    {
	JPanel p = new JPanel(new GridLayout(2, 1));

	playerhumanity = new JComboBox();

	p.add(new JLabel("Slot"));
	p.add(createSlotPanel());

	return p;
    }

    private JPanel createSlotPanel()
    {
	JPanel p = new JPanel();
	p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

	String[] sorts;
	if ( ! singlePlayer || (i == 0))
	{
	    sorts = langage.sort();
	}
	else
	{
	    sorts = new String[]{"Bot","Closed"};
	}
	playerhumanity[i] = new JComboBox(sorts);
	playerhumanity[i].setPreferredSize(COMBOBOX_DIM);
	playerhumanity[i].addActionListener(this);

	playerteam[i] = new JComboBox(new String[]
	{
	    langage.red(), langage.blue(), langage.green()
	});
	playerteam[i].setAlignmentX(LEFT_ALIGNMENT);
	playerteam[i].setSize(PLAYER_COLUMN_DIM);
	playerteam[i].addActionListener(new ActionListener()
	{
	    public void actionPerformed(ActionEvent e)
	    {
		if (i == sock.getPlayerNum())
		{
		    sock.team(playerteam[i].getSelectedIndex());
		}
		else
		{
		    if (sock.isServer()
			    && playerhumanity[i].getSelectedItem().toString().equals(langage.bot()))
		    {
			sock.team(playerteam[i].getSelectedIndex(), i);
		    }
		}
	    }
	});

	p.add(playerhumanity[i]);
	p.add(playerteam[i]);

	return p;
    }

    private JPanel createPlayerColumn()
    {
	JPanel p = new JPanel();
	p.setLayout(new GridLayout(5, 1));

	playername = new JTextField[4];

	p.add(new JLabel(langage.playerName()));
	p.add(createPlayerPanel(0));
	p.add(createPlayerPanel(1));
	p.add(createPlayerPanel(2));
	p.add(createPlayerPanel(3));

	return p;
    }

    private JPanel createPlayerPanel(int i)
    {
	JPanel p = new JPanel();
	p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

	playername[i] = new JTextField();
	playername[i].setAlignmentX(LEFT_ALIGNMENT);
	playerteam[i].setSize(50, 30);
	playername[i].setEditable(false);

	p.add(playername[i]);

	return p;
    }

    private JPanel createReadyColumn()
    {
	JPanel p = new JPanel();
	p.setLayout(new GridLayout(5, 1));

	playerready = new JCheckBox[4];

	JLabel top = new JLabel(langage.ready());
	top.setAlignmentX(CENTER_ALIGNMENT);
	playerready[0] = new JCheckBox();
	playerready[1] = new JCheckBox();
	playerready[2] = new JCheckBox();
	playerready[3] = new JCheckBox();

	p.add(top);
	playerready[0].setAlignmentX(LEFT_ALIGNMENT);
	playerready[1].setAlignmentX(LEFT_ALIGNMENT);
	playerready[2].setAlignmentX(LEFT_ALIGNMENT);
	playerready[3].setAlignmentX(LEFT_ALIGNMENT);

	playerready[0].setPreferredSize(READY_COLUMN_DIM);
	playerready[1].setPreferredSize(READY_COLUMN_DIM);
	playerready[2].setPreferredSize(READY_COLUMN_DIM);
	playerready[3].setPreferredSize(READY_COLUMN_DIM);

	p.add(playerready[0]);
	p.add(playerready[1]);
	p.add(playerready[2]);
	p.add(playerready[3]);

	return p;

    }

    private JPanel createGameSettingsPanel(boolean sing)
    {
	JPanel p = new JPanel(new BorderLayout());
	JPanel settings = new JPanel(new GridLayout(7, 2));

	teamplay = new JCheckBox();
	teamplay.addActionListener(new ActionListener()
	{
	    public void actionPerformed(ActionEvent arg0)
	    {
		setTeamPlay(teamplay.isSelected());
		sock.sendLobbyData();
	    }
	});

	GameType[] gametypes = null;
	if (sing)
	{
	    gametypes = new GameType[]
	    {
		SINGLEPLAYER, SURVIVAL, OISURVIVAL, RACE, ZSRACE
	    };
	}
	else
	{
	    gametypes = new GameType[]
	    {
		SURVIVAL, OISURVIVAL, RACE, ZSRACE
	    };
	}

	gametype = new JComboBox(gametypes);
	gametype.addActionListener(new ActionListener()
	{
	    public void actionPerformed(ActionEvent e)
	    {
		((GameType) gametype.getSelectedItem()).onSelection();
	    }
	});

	settings.add(new JLabel(langage.gameType()));
	settings.add(gametype);
	settings.add(new JLabel(langage.teamPlay()));
	settings.add(teamplay);

	startlvl = new JComboBox(new String[]
	{
	    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
	});
	settings.add(new JLabel(langage.startlvl()));
	settings.add(startlvl);
	startlvl.addActionListener(this);

	botlvl = new JComboBox(langage.botDifficulty());
	settings.add(new JLabel(langage.difficulty()));
	settings.add(botlvl);
	botlvl.addActionListener(this);


	opt1 = new JComboBox(new String[]
	{
	    "200000", "100000", "80000", "50000", "20000", "10000"
	});
	opt1label = new JLabel(langage.scoreToWin());
	settings.add(opt1label);
	settings.add(opt1);
	opt1.setVisible(false);
	opt1label.setVisible(false);
	opt1.addActionListener(this);

	opt2 = new JComboBox();
	opt2label = new JLabel();
	settings.add(opt2label);
	settings.add(opt2);
	opt2.setVisible(false);
	opt2label.setVisible(false);

	start = SwingUtils.newDefaultButton(langage.start());

	addBorder(p, langage.settings());

	p.add(settings, "North");
	p.add(start, "South");
	p.setVisible(true);
	return p;
    }

    private JPanel createChatPanel()
    {
	JPanel panel = new JPanel();
	addBorder(panel, langage.chatLog());
	panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

	chatLog = new JTextArea(langage.lobby());
	chatField = new JTextField();
	chatField.addKeyListener(new ChatSendController(this));
	chatLog.setEditable(false);
	chatLog.setLineWrap(true);
	JScrollPane chatScroll = new JScrollPane(chatLog);

	chatScroll.setPreferredSize(new Dimension(640, 180));

	panel.add(chatScroll);
	panel.add(chatField);

	return panel;
    }

    private boolean teamPlay()
    {
	return teamplay.isSelected();
    }

    private void addBorder(JPanel p, String title)
    {
	p.setBorder(BorderFactory.createCompoundBorder(
		BorderFactory.createTitledBorder(title),
		BorderFactory.createEmptyBorder(5, 5, 5, 5)));
    }

    public void updateStartButton()
    {
	if ( ! sock.isServer())
	{
	    return;
	}

	for (int i = 0; i < 4; i ++)
	{
	    if ( ! playerready[i].isSelected())
	    {
		start.setEnabled(false);
		return;
	    }
	}
	start.setEnabled(true);
    }

    public JButton getStartButton()
    {
	return start;
    }

    public JComboBox getStartLevel()
    {
	return startlvl;
    }

    public JComboBox getBotlvl()
    {
	return botlvl;
    }

    public JComboBox[] getSlots()
    {
	return playerhumanity;
    }

    public void setPlayerName(String name)
    {
	playername[0].setText(name);
    }

    public void setPlayerName(String name, int i)
    {
	playername[i].setText(name);
    }

    public String getPlayerName(int i)
    {
	return playername[i].getText();
    }

    public boolean isPlayerReady(int i)
    {
	return playerready[i].isSelected();
    }

    public void setPlayerReady(int i, boolean ready)
    {
	playerready[i].setSelected(ready);
	updateStartButton();
    }

    public void setPlayerTeam(int i, byte team)
    {
	playerteam[i].setSelectedIndex(team);
    }

    //Use to turn the Team Play checkbox on/off
    public void setTeamPlayAllowed(boolean allow)
    {
	if (sock != null && sock.isServer())
	{
	    teamplay.setEnabled(allow);
	}
	if ( ! allow)
	{
	    teamplay.setSelected(false);
	}
	setTeamPlay(teamplay.isSelected());
    }
    //Use when Team Play check box is invoked

    public void setTeamPlay(boolean on)
    {
	if (sock != null)
	{
	    if (sock.isServer())
	    {
		for (int i = 1; i < 4; i ++)
		{
		    if (playerhumanity[i].getSelectedItem().equals(langage.bot()))
		    {
			playerteam[i].setEnabled(on);
		    }
		}
	    }
	    playerteam[sock.getPlayerNum()].setEnabled(on);
	} //For init only:
	else
	{
	    for (int i = 0; i < 4; i ++)
	    {
		playerteam[i].setEnabled(false);
	    }
	}
    }

    public JCheckBox getPlayerReady(int i)
    {
	return playerready[i];
    }
    //public void setReadyEnabled(int i, boolean ready) {playerready[i].setEnabled(ready);}

    public JTextField getPlayerField(int i)
    {
	return playername[i];
    }

    public boolean[] getClosed()
    {
	return closed;
    }

    public boolean isBot(int i)
    {
	return ((String) playerhumanity[i].getSelectedItem()).equals(langage.bot());
    }

    public void setHuman(int i)
    {
	playerready[i].setSelected(false);
	playername[i].setText(langage.openSlot());
	closed[i] = false;

	updateStartButton();
	openclose(true, i);
	sock.sendLobbyData();
    }

    public void setOpenHumanText(int i)
    {
	playername[i].setText(langage.openSlot());
    }

    public void setBot(int i)
    {
	playerready[i].setSelected(true);
	playername[i].setText("  < BOT >");
	closed[i] = false;
	int j;
	if (singlePlayer)
	{
	    j = 0;
	}
	else
	{
	    j = 1;
	}
	playerhumanity[i].setSelectedIndex(j);
	updateStartButton();
	openclose(false, i);
	sock.sendLobbyData();
	if (sock.isServer())
	{
	    playerteam[i].setEnabled(teamplay.isSelected());
	}
    }

    public void setClosed(int i)
    {
	playerready[i].setSelected(true);
	playername[i].setText(langage.closeSlot());
	closed[i] = true;
	int j;
	if (singlePlayer)
	{
	    j = 1;
	}
	else
	{
	    j = 2;
	}
	playerhumanity[i].setSelectedIndex(j);
	updateStartButton();

	openclose(false, i);
	sock.sendLobbyData();
	playerteam[i].setEnabled(false);
    }

    private void openclose(boolean open, int i)
    {
	if (sock instanceof TCPServer)
	{
	    TCPServer svr = (TCPServer) sock;
	    svr.guiOpen(open, i);
	}
    }

    public void prepareForSinglePlayer()
    {
	setClosed(1);
	setClosed(2);
	setClosed(3);

	for (int i = 1; i < 4; i ++)
	{
	    closed[i] = true;
	}
    }

    public void prepareForMultiPlayer()
    {
	setHuman(1);
	setHuman(2);
	setHuman(3);

	for (int i = 1; i < 4; i ++)
	{
	    closed[i] = false;
	}
    }

    public Game makeGame()
    {
	GameType gt = (GameType) gametype.getSelectedItem();
	return gt.getGame();
    }

    public void addActionListeners(ActionListener l)
    {
	start.addActionListener(l);
	for (int i = 0; i < 4; i ++)
	{
	    playerhumanity[i].addActionListener(l);
	    playerready[i].addActionListener(l);
	}
    }

    //Envoyer un msg
    public void sendChat()
    {
	String s = chatField.getText();
	if (s == null || s.equals(""))
	{
	    return;
	}

	chatField.setText("");
	printChat(s, Settings.PLAYER_NAME);

	sock.sendMessage(s);
    }
    //Recevoir un msg

    public void printChat(String msg, String playername)
    {
	print(playername + " :  " + msg);
    }

    public void printPlayerJoin(String name)
    {
	print(name + langage.entered());
    }

    public void printPlayerLeft(String name)
    {
	print(name + langage.hasLeft());
    }

    public void printPlayerKick(String name)
    {
	print(name + langage.kicked());
    }

    private void print(String s)
    {
	chatLog.append("\n" + s);
	chatLog.setText(chatLog.getText());
    }

    public void setTCPSocket(TCPSocket tcpsock)
    {
	sock = tcpsock;
	if ( ! sock.isServer())
	{
	    start.setEnabled(false);
	    teamplay.setEnabled(false);
	    gametype.setEnabled(false);
	    startlvl.setEnabled(false);
	    botlvl.setEnabled(false);
	    opt1.setEnabled(false);
	    opt2.setEnabled(false);
	    playerhumanity[1].setEnabled(false);
	    playerhumanity[2].setEnabled(false);
	    playerhumanity[3].setEnabled(false);
	}
	int playernum = sock.getPlayerNum();
	for (int i = 0; i < 4; i ++)
	{
	    if (i != playernum)
	    {
		playerready[i].setEnabled(false);
	    }
	    else
	    {
		playerready[i].setEnabled(true);
	    }
	}

	new Thread(sock).start();
    }

    public TCPSocket getTCPSocket()
    {
	return sock;
    }

    public synchronized LobbyData asLobbyData()
    {
	byte slot[] = new byte[4];
	boolean ready[] = new boolean[4];
	String name[] = new String[4];

	for (int i = 0; i < 4; i ++)
	{
	    slot[i] = (byte) this.playerhumanity[i].getSelectedIndex();
	    ready[i] = this.playerready[i].isSelected();
	    name[i] = this.playername[i].getText();
	}
	//TODO: teamplay, botlvl, startlvl, gametype, opt1
	return new LobbyData(
		slot,
		(byte) gametype.getSelectedIndex(),
		ready,
		teamplay.isSelected(),
		(byte) botlvl.getSelectedIndex(),
		(byte) startlvl.getSelectedIndex(),
		(byte) opt1.getSelectedIndex(),
		name);
    }

    public synchronized LobbyInit asLobbyInit()
    {
	boolean ready[] = new boolean[4];
	byte team[] = new byte[4];
	for (int i = 0; i < 4; i ++)
	{
	    ready[i] = this.playerready[i].isSelected();
	    team[i] = (byte) this.playerteam[i].getSelectedIndex();
	}
	return new LobbyInit(ready, team);
    }

    public void refreshLobbyData(LobbyData ld)
    {
	for (int i = 1; i < 4; i ++)
	{
	    playerhumanity[i].setSelectedIndex(ld.slot[i]);
	    playerready[i].setSelected(ld.ready[i]);
	    playername[i].setText(ld.name[i]);
	    gametype.setSelectedIndex(ld.gametype);
	    teamplay.setSelected(ld.teamplay);
	    botlvl.setSelectedIndex(ld.botlvl);
	    startlvl.setSelectedIndex(ld.startlvl);
	    opt1.setSelectedIndex(ld.opt1);
	}
    }

    public void refreshLobbyData(LobbyInit li)
    {
	for (int i = 0; i < 4; i ++)
	{
	    playerready[i].setSelected(li.ready[i]);
	    playerteam[i].setSelectedIndex(li.team[i]);
	}
    }

    public void notifyReadyChange(JCheckBox box)
    {
	for (int i = 0; i < 4; i ++)
	{
	    if (box.equals(playerready[i]))
	    {
		if (i == sock.getPlayerNum())
		{
		    sock.ready(playerready[i].isSelected());
		}
	    }
	}
    }
    private GameType SURVIVAL = initSurvival();
    private GameType OISURVIVAL = initOISurvival();
    private GameType SINGLEPLAYER = initSinglePlayer();
    private GameType RACE = initRace();
    private GameType ZSRACE = initZSRace();

    private GameType initSurvival()
    {
	GameType ret = new GameType(langage.survival())
	{
	    public Game getGame()
	    {
		setGUITeamColors();
		if (teamplay.isSelected())
		{
		    return new SurvivalGame(makePlayers(), getTeams());
		}
		else
		{
		    return new SurvivalGame(makePlayers());
		}
	    }
	};
	return ret;
    }

    private GameType initOISurvival()
    {
	GameType ret = new GameType(langage.sticksAndStones())
	{
	    public Game getGame()
	    {
		setGUITeamColors();
		if (teamplay.isSelected())
		{
		    //1) J r'ajouter ca:
		    return new OISurvivalGame(makePlayers(), getTeams());
		}
		else
		{
		    return new OISurvivalGame(makePlayers());
		}
	    }
	};
	return ret;
    }

    private GameType initSinglePlayer()
    {
	GameType ret = new GameType(langage.singlePlayer())
	{
	    public Game getGame()
	    {
		GUIController.current.setTeamColors(new int[]
		{
		    0, 0, 0, 0
		});
		return new SinglePlayerGame((Human) makePlayer(0));
	    }

	    @Override
	    void onSelection()
	    {
		setTeamPlayAllowed(false);
		setClosed(1);
		setClosed(2);
		setClosed(3);
		playerhumanity[1].setEnabled(false);
		playerhumanity[2].setEnabled(false);
		playerhumanity[3].setEnabled(false);
		opt1.setVisible(false);
		opt1label.setVisible(false);
		GUIController.current.setTeamColors(new int[]
		{
		    0, 0, 0, 0
		});
	    }
	};
	return ret;
    }

    private GameType initRace()
    {
	GameType ret = new GameType(langage.race())
	{
	    public Game getGame()
	    {
		GUIController.current.setTeamColors(new int[]
		{
		    0, 0, 0, 0
		});
		return new RaceGame(makePlayers(),
			Integer.parseInt(opt1.getSelectedItem().toString()));
	    }

	    @Override
	    void onSelection()
	    {
		super.onSelection();
		opt1.setVisible(true);
		opt1label.setVisible(true);
		setTeamPlayAllowed(false);
	    }
	};
	return ret;
    }

    private GameType initZSRace()
    {
	GameType ret = new GameType(langage.zedeness())
	{
	    public Game getGame()
	    {
		GUIController.current.setTeamColors(new int[]
		{
		    0, 0, 0, 0
		});
		return new ZSRaceGame(makePlayers(),
			Integer.parseInt(opt1.getSelectedItem().toString()));
	    }

	    @Override
	    void onSelection()
	    {
		super.onSelection();
		opt1.setVisible(true);
		opt1label.setVisible(true);
		setTeamPlayAllowed(false);
	    }
	};
	return ret;
    }

    abstract class GameType
    {
	String name;

	GameType(String name)
	{
	    this.name = name;
	}

	//Modification a faire quand ce gametype est selectionner.
	//  e.x. pour single player: close tout et setEnable(false).
	void onSelection()
	{
	    if (sock != null && sock.isServer())
	    {
		playerhumanity[1].setEnabled(true);
		playerhumanity[2].setEnabled(true);
		playerhumanity[3].setEnabled(true);
		sock.sendLobbyData();
	    }
	    opt1.setVisible(false);
	    opt1label.setVisible(false);
	    setTeamPlayAllowed(true);
	}

	abstract Game getGame();

	private int getBotLevel()
	{
	    return botlvl.getSelectedIndex() + 1;
	}

	private int getStartLevel()
	{
	    return startlvl.getSelectedIndex();
	}

	Player[] makePlayers()
	{
	    return new Player[]
	    {
		makePlayer(0), makePlayer(1), makePlayer(2), makePlayer(3)
	    };
	}

	Player makePlayer(int num)
	{
	    int sl = getStartLevel();
	    //IF CLOSED:
	    if (closed[num])
	    {
		return null;
	    } //IF BOT:
	    else
	    {
		if (playerhumanity[num].getSelectedItem().toString().equals(langage.bot()))
		{
		    int ai = getBotLevel();
		    if (sock.isServer())
		    {
			return new Bot(num, sl, ai);
		    }
		    else
		    {
			return new ExternalPlayer(ai, num, sl);
		    }
		} //IF HUMAN:
		else
		{

		    if (playerhumanity[num].getSelectedItem().toString().equals(langage.human()))
		    {
			if (num == sock.getPlayerNum())
			{
			    return new Human(playername[num].getText(), num, sl);
			}
			else
			{
			    return new ExternalPlayer(playername[num].getText(), num, sl);
			}
		    }
		}
	    }
	    throw new UnknownError("something's not right");
	}

	int[] getTeams()
	{
	    //TODO: fix for lang
	    int[] ret = new int[4];
	    for (int i = 0; i < 4; i ++)
	    {
		if (playerhumanity[i].getSelectedItem().toString().equals(langage.closed()))
		{
		    ret[i] = 0;
		}
		else
		{
		    ret[i] = playerteam[i].getSelectedIndex() + 1;
		}
	    }
	    return ret;
	}

	void setGUITeamColors()
	{
	    if (teamplay.isSelected())
	    {
		GUIController.current.setTeamColors(new int[]
		{
		    playerteam[0].getSelectedIndex() + 1,
		    playerteam[1].getSelectedIndex() + 1,
		    playerteam[2].getSelectedIndex() + 1,
		    playerteam[3].getSelectedIndex() + 1
		});
	    }
	    else
	    {
		GUIController.current.setTeamColors(new int[]
		{
		    0, 0, 0, 0
		});
	    }
	}

	@Override
	public String toString()
	{
	    return name;
	}
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
	sock.sendLobbyData();
    }
    * */
}